package geppetto.reordering;

import geppetto.cat.alignments.Alignment;
import geppetto.cat.alignments.AlignmentsCache;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.cat.corpus.BilingualCorpus;
import geppetto.phraseHMM.phraseExtraction.extractedphrase.ExtractedPhrasePair;
import gnu.trove.TIntDoubleHashMap;

public class PurposeBasedMSDReorderingModel extends MSDReorderingCalculator{
	protected REO_MODEL_TYPE modelType;
	AlignmentsSet set;
	AlignmentsCache _cache;
	BilingualCorpus _corpus;
	String _type;
	double falseWeight = 0.05;
	double trueWeight = 1;

	protected TIntDoubleHashMap prevSmoothingFactors = new TIntDoubleHashMap();
	protected TIntDoubleHashMap nextSmoothingFactors = new TIntDoubleHashMap();

	public PurposeBasedMSDReorderingModel(REO_MODEL_TYPE modelType,AlignmentsSet set, BilingualCorpus corpus, String type) {
		this(DEFAULTSMOOTHING,modelType, set, corpus, type);
	}

	public PurposeBasedMSDReorderingModel(double smoothing, REO_MODEL_TYPE modelType,AlignmentsSet set, BilingualCorpus corpus, String type) {
		super(smoothing, modelType, set);
		this.modelType = modelType;
		this.set = set;
		this._corpus = corpus;
		this._type = type;
		setSmoothing(smoothing);
		_cache = new AlignmentsCache(set);
	}

	public PurposeBasedMSDReorderingModel(AlignmentsSet set, BilingualCorpus corpus, String type) {
		this(REO_MODEL_TYPE.REO_MSD, set, corpus, type);
	}

	@Override
	public ReorderingInfo getReorderingInfo(ExtractedPhrasePair epp){
		 int sentenceNumber = epp.getSentenceNumber();
		 int startS = epp.getSourceStartPos();
		 int endS = epp.getSourceEndPos();
		 int startT = epp.getForeignStartPos();
		 int endT = epp.getForeignEndPos(); 
		 
		Alignment alignment = set.get(sentenceNumber);
		boolean connectedLeftTopP = isAligned(alignment, startS-1, startT-1);
		boolean connectedRightTopP = isAligned(alignment,endS+1, startT-1 );
		boolean connectedLeftTopN = isAligned(alignment,endS+1, endT+1 );
		boolean connectedRightTopN = isAligned(alignment,startS-1, endT+1 ); 

		double probLeftP = connectedLeftTopP && !connectedRightTopP ? 1 : 0;
		double probRightP = connectedRightTopP && !connectedLeftTopP ? 1 : 0;
		double probUnkP = probLeftP == 0 && probRightP == 0 ? 1 : 0;
		double probLeftN = connectedLeftTopN && !connectedRightTopN ? 1 : 0;
		double probRightN = connectedRightTopN && !connectedLeftTopN ? 1 : 0;
		double probUnkN = probLeftN == 0 && probRightN == 0 ? 1 : 0; 
		
		ReorderingInfo info = new ReorderingInfo();

		double prob = falseWeight;
		if(rightType(sentenceNumber, startS, endS, startT, endT)){
			prob = trueWeight;
		}
		info.addPrevWordOrientation(convertREO_POS(REO_POS.LEFT), probLeftP * prob);
		info.addPrevWordOrientation(convertREO_POS(REO_POS.RIGHT), probRightP * prob);
		info.addPrevWordOrientation(convertREO_POS(REO_POS.UNKNOWN), probUnkP * prob);
		info.addNextWordOrientation(convertREO_POS(REO_POS.LEFT), probLeftN * prob);
		info.addNextWordOrientation(convertREO_POS(REO_POS.RIGHT), probRightN * prob);
		info.addNextWordOrientation(convertREO_POS(REO_POS.UNKNOWN), probUnkN * prob);
		
		return info;
	}

	private boolean rightType(int sentenceNumber, int startS,
			int endS, int startT, int endT) {
		if(_type.toLowerCase().equals("affirmative") || _type.toLowerCase().equals("a")){
			return detectAffirmative(sentenceNumber, startS, endS, startT, endT);
		}
		if(_type.toLowerCase().equals("interrogative") || _type.toLowerCase().equals("i")){
			return detectInterrogative(sentenceNumber, startS, endS, startT, endT);
		}
		if(_type.toLowerCase().equals("exclamative") || _type.toLowerCase().equals("e")){
			return detectExclamative(sentenceNumber, startS, endS, startT, endT);
		}
		if(_type.toLowerCase().equals("declarative") || _type.toLowerCase().equals("d")){
			return detectDeclarative(sentenceNumber, startS, endS, startT, endT);
		}
		return false;
	}

	private boolean detectAffirmative(int sentenceNumber, int startS,
			int endS, int startT, int endT){
		return findIfNextPunctuationMatches(sentenceNumber, startS, endS, startT, endT, ".");
	}

	private boolean detectInterrogative(int sentenceNumber, int startS,
			int endS, int startT, int endT){
		return findIfNextPunctuationMatches(sentenceNumber, startS, endS, startT, endT, "?");
	}
	private boolean detectExclamative(int sentenceNumber, int startS,
			int endS, int startT, int endT){
		return findIfNextPunctuationMatches(sentenceNumber, startS, endS, startT, endT, "!");
	}
	private boolean detectDeclarative(int sentenceNumber, int startS,
			int endS, int startT, int endT){
		return findIfNextPunctuationMatches(sentenceNumber, startS, endS, startT, endT, ".");
	}
	
	private boolean findIfNextPunctuationMatches(int sentenceNumber, int startS,
			int endS, int startT, int endT, String match){
		boolean sourceIsCorrect = false;
		boolean targetIsCorrect = true;//false;
		
		int[] source = _corpus.getSourceSentence(sentenceNumber, BilingualCorpus.TRAIN_CORPUS);
		int[] target = _corpus.getForeignSentence(sentenceNumber, BilingualCorpus.TRAIN_CORPUS);
		for(int i = endS; i < source.length; i++){
			String sourceC = _corpus.getSourceString(source[i]);
			if (isPunct(sourceC)) {
				if(sourceC.equals(match)){
					sourceIsCorrect = true;
				}
				break;
			}
		}
		/*for(int j = endT; j < target.length; j++){
			String targetC = _corpus.getForeignString(target[j]);
			if (isPunct(targetC)) {
				if(targetC.equals(match)){
					targetIsCorrect = true;
				}
				break;
			} 
		}*/
		return sourceIsCorrect && targetIsCorrect;
	}

	public boolean isPunct(String s) {
		if (s.equalsIgnoreCase(".")) {
			return true;
		} else if (s.equalsIgnoreCase("!")) {
			return true;
		} else if (s.equalsIgnoreCase("?")) {
			return true;
		} else {
			return false;
		}
	}
}
